package com.sum.tea.xinlian.viewmodel

import androidx.lifecycle.*
import com.sum.tea.contants.AppConfig
import com.uhf.api.cls.Reader
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class Sub3TabViewModel : ViewModel() {

    private val _toastMessage = MutableLiveData<String>()
    val toastMessage: LiveData<String> get() = _toastMessage

    private val _readData = MutableLiveData<String>()
    val readData: LiveData<String> get() = _readData

    private val myapp = AppConfig.getInstance()

    private var g2tf: Reader.TagFilter_ST? = null

    // ������ԭ�з�����һ��
    fun SetOpant(selectedOpant: Int) {
        myapp.Rparams.opant = selectedOpant + 1
    }

    fun SetPassword(isChecked: Boolean, password: String) {
        myapp.Rparams.password = if (isChecked) password else ""
    }

    fun ClearFiler() {
        g2tf = null
        myapp.Mreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_TAG_FILTER, g2tf)
    }

    fun SetFiler(
        enableFilter: Boolean,
        filterData: String,
        filterAddress: Int,
        filterBank: Int,
        matchType: Int
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    if (myapp.nxpu8 != 0) {
                        _toastMessage.postValue("NXP U8 MODE is using")
                        return@withContext
                    }

                    if (enableFilter) {
                        val ln = filterData.length
                        val adjustedLength = if (ln == 1 || ln % 2 == 1) ln + 1 else ln
                        val fdata = ByteArray(adjustedLength / 2)
                        myapp.Mreader.Str2Hex(filterData, filterData.length, fdata)

                        g2tf = myapp.Mreader.TagFilter_ST().apply {
                            this.fdata = fdata
                            this.flen = filterData.length * 4
                            this.isInvert = if (matchType == 1) 1 else 0
                            this.bank = filterBank + 1
                            this.startaddr = filterAddress
                        }

                        val er = myapp.Mreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_TAG_FILTER, g2tf)
                        if (er == Reader.READER_ERR.MT_OK_ERR) {
                            _toastMessage.postValue("${AppConfig.Constr_ok} $er")
                        } else {
                            _toastMessage.postValue("${AppConfig.Constr_failed} $er")
                        }
                    } else {
                        g2tf = null
                        myapp.Mreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_TAG_FILTER, g2tf)
                    }
                } catch (e: Exception) {
                    _toastMessage.postValue("${AppConfig.Constr_excep} ${e.message}")
                }
            }
        }
    }

    fun readOperation(
        count: Int,
        address: Int,
        dataType: Int,
        bank: Int,
        password: String,
        optime: Short
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val rdata = ByteArray(count * 2)
                    val rpaswd = if (password.isNotEmpty()) {
                        ByteArray(4).apply { myapp.Mreader.Str2Hex(password, password.length, this) }
                    } else {
                        ByteArray(4)
                    }

                    var er = Reader.READER_ERR.MT_OK_ERR
                    var trycount = 1
                    do {
                        er = myapp.Mreader.GetTagData(
                            myapp.Rparams.opant,
                            bank.toChar(),
                            address,
                            count,
                            rdata,
                            rpaswd,
                            optime
                        )
                        if (er != Reader.READER_ERR.MT_OK_ERR) {
                            myapp.Mreader.GetLastDetailError(myapp.ei)
                        }

                        trycount--
                        if (trycount < 1) break
                    } while (er != Reader.READER_ERR.MT_OK_ERR)

                    if (er == Reader.READER_ERR.MT_OK_ERR) {
                        val valStr = when (dataType) {
                            0 -> {
                                val out = CharArray(rdata.size * 2)
                                myapp.Mreader.Hex2Str(rdata, rdata.size, out)
                                String(out)
                            }
                            1 -> {
                                val out = CharArray(rdata.size)
                                for (i in rdata.indices) {
                                    out[i] = rdata[i].toChar()
                                }
                                String(out)
                            }
                            2 -> {
                                String(rdata, charset("GBK"))
                            }
                            else -> ""
                        }
                        _readData.postValue(valStr)
                        _toastMessage.postValue("${AppConfig.Constr_ok} $er")
                    } else {
                        _toastMessage.postValue("${AppConfig.Constr_failed} $er")
                    }
                } catch (e: Exception) {
                    _toastMessage.postValue("${AppConfig.Constr_excep} ${e.message}")
                } finally {
                    ClearFiler()
                }
            }
        }
    }

    fun writeOperation(
        data: ByteArray,
        address: Int,
        bank: Int,
        password: String,
        optime: Short
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val rpaswd = if (password.isNotEmpty()) {
                        ByteArray(4).apply { myapp.Mreader.Str2Hex(password, password.length, this) }
                    } else {
                        ByteArray(4)
                    }

                    var er = Reader.READER_ERR.MT_OK_ERR
                    var trycount = 1
                    do {
                        er = myapp.Mreader.WriteTagData(
                            myapp.Rparams.opant,
                            bank.toChar(),
                            address,
                            data,
                            data.size,
                            rpaswd,
                            optime
                        )
                        if (er != Reader.READER_ERR.MT_OK_ERR) {
                            myapp.Mreader.GetLastDetailError(myapp.ei)
                        }

                        trycount--
                        if (trycount < 1) break
                    } while (er != Reader.READER_ERR.MT_OK_ERR)

                    if (er == Reader.READER_ERR.MT_OK_ERR) {
                        _toastMessage.postValue("${AppConfig.Constr_ok} $er")
                    } else {
                        _toastMessage.postValue("${AppConfig.Constr_failed} $er")
                    }
                } catch (e: Exception) {
                    _toastMessage.postValue("${AppConfig.Constr_excep} ${e.message}")
                } finally {
                    ClearFiler()
                }
            }
        }
    }

    fun writeEpcOperation(
        data: ByteArray,
        password: String,
        optime: Short
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val rpaswd = if (password.isNotEmpty()) {
                        ByteArray(4).apply { myapp.Mreader.Str2Hex(password, password.length, this) }
                    } else {
                        ByteArray(4)
                    }

                    var er = Reader.READER_ERR.MT_OK_ERR
                    var trycount = 1
                    do {
                        er = myapp.Mreader.WriteTagEpcEx(
                            myapp.Rparams.opant,
                            data,
                            data.size,
                            rpaswd,
                            optime
                        )
                        if (er != Reader.READER_ERR.MT_OK_ERR) {
                            myapp.Mreader.GetLastDetailError(myapp.ei)
                        }

                        trycount--
                        if (trycount < 1) break
                    } while (er != Reader.READER_ERR.MT_OK_ERR)

                    if (er == Reader.READER_ERR.MT_OK_ERR) {
                        _toastMessage.postValue("${AppConfig.Constr_ok} $er")
                    } else {
                        _toastMessage.postValue("${AppConfig.Constr_failed} $er")
                    }
                } catch (e: Exception) {
                    _toastMessage.postValue("${AppConfig.Constr_excep} ${e.message}")
                } finally {
                    ClearFiler()
                }
            }
        }
    }

    fun lockOperation(
        lockObj: Reader.Lock_Obj,
        lockType: Reader.Lock_Type,
        password: String,
        optime: Short
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val rpaswd = if (password.isNotEmpty()) {
                        ByteArray(4).apply { myapp.Mreader.Str2Hex(password, password.length, this) }
                    } else {
                        ByteArray(4)
                    }

                    val er = myapp.Mreader.LockTag(
                        myapp.Rparams.opant,
                        lockObj.value().toByte(),
                        lockType.value().toShort(),
                        rpaswd,
                        optime
                    )

                    if (er == Reader.READER_ERR.MT_OK_ERR) {
                        _toastMessage.postValue(AppConfig.Constr_sub3lockok)
                    } else {
                        _toastMessage.postValue(AppConfig.Constr_sub3lockfail)
                    }
                } catch (e: Exception) {
                    _toastMessage.postValue("${AppConfig.Constr_excep} ${e.message}")
                } finally {
                    ClearFiler()
                }
            }
        }
    }

    fun killOperation(
        password: String,
        optime: Short
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val rpaswd = if (password.isNotEmpty()) {
                        ByteArray(4).apply { myapp.Mreader.Str2Hex(password, password.length, this) }
                    } else {
                        ByteArray(4)
                    }

                    val er = myapp.Mreader.KillTag(
                        myapp.Rparams.opant,
                        rpaswd,
                        optime
                    )

                    if (er == Reader.READER_ERR.MT_OK_ERR) {
                        _toastMessage.postValue(AppConfig.Constr_killok)
                    } else {
                        _toastMessage.postValue(AppConfig.Constr_killfailed)
                    }
                } catch (e: Exception) {
                    _toastMessage.postValue("${AppConfig.Constr_excep} ${e.message}")
                } finally {
                    ClearFiler()
                }
            }
        }
    }

    fun testWriteOperation(
        address: Int,
        bank: Int,
        dataType: Int,
        password: String,
        optime: Short
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val rd = java.util.Random(System.currentTimeMillis())
                    val data = ByteArray(12).apply { rd.nextBytes(this) }
                    // Assuming Reader.bytes_Hexstr is a utility function to convert bytes to hex string
                    _readData.postValue(Reader.bytes_Hexstr(data))

                    val rpaswd = if (password.isNotEmpty()) {
                        ByteArray(4).apply { myapp.Mreader.Str2Hex(password, password.length, this) }
                    } else {
                        ByteArray(4)
                    }

                    var er = Reader.READER_ERR.MT_OK_ERR
                    var trycount = 1
                    do {
                        er = myapp.Mreader.WriteTagData(
                            myapp.Rparams.opant,
                            bank.toChar(),
                            address,
                            data,
                            data.size,
                            rpaswd,
                            optime
                        )
                        if (er != Reader.READER_ERR.MT_OK_ERR) {
                            myapp.Mreader.GetLastDetailError(myapp.ei)
                        }

                        trycount--
                        if (trycount < 1) break
                    } while (er != Reader.READER_ERR.MT_OK_ERR)

                    if (er == Reader.READER_ERR.MT_OK_ERR) {
                        _toastMessage.postValue("${AppConfig.Constr_ok} $er")
                    } else {
                        _toastMessage.postValue("${AppConfig.Constr_failed} $er")
                    }
                } catch (e: Exception) {
                    _toastMessage.postValue("${AppConfig.Constr_excep} ${e.message}")
                } finally {
                    ClearFiler()
                }
            }
        }
    }

    fun setOptime(optime: Int) {
        myapp.Rparams.optime = optime
    }
}
